﻿using Microsoft.Win32;
/*
 *   Copyright 2011 Peter Crossley
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 *  ----------------------------------------------------------------------------
 *  File:       CloudService.cs
 *  Author:     Peter Crossley
 *  ----------------------------------------------------------------------------
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using UEC;

namespace UEC.Service
{
    class CloudService : System.ServiceProcess.ServiceBase  
    {
        private CloudManager manager;
        private Thread worker = null;
        public CloudService(CloudManager manager) 
        {
            this.ServiceName = global::UEC.Properties.Resources.ServiceTitle;
            this.CanStop = true;
            this.CanPauseAndContinue = false;
            this.AutoLog = true;
            this.manager = manager;
        }

        protected override void OnStart(string[] args)
        {
            bool debug = manager.GetValueAsBoolean("Service", "Debug", false);
            manager.Debug = debug;

            manager.LogEvent("Cloud Service Starting.");
            worker = new Thread(new ThreadStart(Execute));
            worker.Start();
            
            manager.OnCloudServiceStart();
            manager.LogEvent("Cloud Service Started.");
        }

        protected override void OnStop()
        {
            manager.LogEvent("Cloud Service Stopping.");
            try
            {
                if(worker !=null) {
                    worker.Abort();
                }
            }
            catch (Exception e)
            {
                manager.LogEvent("Cloud Service Worker thread error:\n" + e.ToString(), System.Diagnostics.EventLogEntryType.Error);
            }
            
            manager.OnCloudServiceStop();
            manager.LogEvent("Cloud Service Stopped.");
        }

        private void Execute()
        {
            manager.LogEvent("Cloud Service Mode: " + (string.IsNullOrEmpty(manager.Mode) ? "normal" : manager.Mode), System.Diagnostics.EventLogEntryType.Information, true);
            //load user data if we have any
            manager.LoadUserDataSettings();
            if (manager.Mode == "sysprep")
            {
                _SysprepServiceRun();
            }
            else if (manager.Mode == null)
            {
                _NormalServiceRun();
            }
            else
            {
                manager.LogEvent("Cloud Service Worker, exiting nothing to do.",System.Diagnostics.EventLogEntryType.Information, true);
            }
        }

        private void _NormalServiceRun()
        {
            manager.OnCloudServiceSetProperties();
            bool firstRun = manager.GetValueAsBoolean("Service", "FirstRun", false);
            if (!firstRun)
            {
                try
                {
                    manager.LogEvent("Cloud Service Run Starting.", System.Diagnostics.EventLogEntryType.Information, true);
                    manager.OnCloudServiceRun();
                    manager.LogEvent("Cloud Service Run Finished.", System.Diagnostics.EventLogEntryType.Information, true);
                    if (manager.Reboot)
                    {
                        manager.OnCloudServiceSystemReboot();
                    }
                }
                catch (Exception e)
                {
                    manager.LogEvent("Cloud Service Worker run error:\n" + e.ToString(), System.Diagnostics.EventLogEntryType.Error, true);
                }

            }
            else
            {
                manager.LogEvent("Cloud Service Run, first run skipping this pass.");
                manager.DeleteKey("Service", "FirstRun");
            }
        }

        private void _SysprepServiceRun() {
            try
            {
                //validate sysprep state
                RegistryKey key = Registry.LocalMachine;
                key = key.OpenSubKey("SYSTEM").OpenSubKey("Setup", true);

                if (key != null)
                {
                    int value = (int)key.GetValue("SetupPhase", -1);
                    if (value != 0)
                    {
                        for (int i = 0; (i < 6 && value != 0); i++)
                        {
                            manager.WriteConsole("Cloud Service: Sysprep not yet finished, sleeping for 10 seconds. (retry: " + (i +1) + " value: " + value + ")");
                            Thread.Sleep(10000); //sleep for 10 secs
                            value = (int)key.GetValue("SetupPhase", -1);                            
                        }
                        if (value != 0)
                        {
                            manager.LogEvent("Cloud Service: Sysprep not yet finished, waiting till next phase. (" + value + ")", System.Diagnostics.EventLogEntryType.Information, true);
                            return;
                        }
                    }
                }

                manager.LogEvent("Cloud Service Sysprep Starting.", System.Diagnostics.EventLogEntryType.Information, true);

                manager.OnCloudServiceSysprep();
                if (manager.Reboot)
                {
                    //wait 30 seconds to reboot to to make sure all system processes are finished
                    manager.OnCloudServiceSystemReboot(30);
                }
                manager.DeleteKey("Service", "FirstRun");
                manager.LogEvent("Cloud Service Sysprep Finished.", System.Diagnostics.EventLogEntryType.Information, true);
            }
            catch (Exception e)
            {
                manager.LogEvent("Cloud Service Worker run error:\n" + e.ToString(), System.Diagnostics.EventLogEntryType.Error, true);
            }
        }
    }
}
